from .memory import *
import ctypes
from .utils import get_functions, MessageColor
from pycparser import c_ast, c_parser, parse_file


def get_ctypes_default_value(type_name):
    type_mapping = {
        'int': c_int,
        'unsigned int': c_uint,
        'short': c_short,
        'unsigned short': c_ushort,
        'float': c_float,
        'double': c_double,
        'char': c_char
    }
    c_type = type_mapping.get(type_name.lower(), None)
    if c_type is None:
        raise ValueError(f"Unsupported type: {type_name}")
    return c_type().value

def get_ctypes_value(type_name, value):
    type_mapping = {
        'int': c_int,
        'unsigned int': c_uint,
        'short': c_short,
        'unsigned short': c_ushort,
        'float': c_float,
        'double': c_double,
        'char': c_char
    }
    c_type = type_mapping.get(type_name.lower(), None)
    if c_type is None:
        raise ValueError(f"Unsupported type: {type_name}")
    return c_type(value)


def cast_ctypes_value(value, target_type_name):
    """
    检查value的ctypes类型是否与target_type_name匹配，不匹配则进行cast转换
    返回转换后的ctypes对象
    """
    # 定义类型名称到ctypes类型的映射
    type_map = {
        "int": c_int,
        "unsigned int": c_uint,
        "short": c_short,
        "unsigned short": c_ushort,
        "float": c_float,
        "double": c_double,
        "char": c_char
    }

    # 规范化目标类型名称
    normalized_target = target_type_name.strip().lower()
    target_type = next((t for t_name, t in type_map.items() 
                        if normalized_target == t_name.lower()), None)
    if not target_type:
        raise ValueError(f"Unsupported target type: {target_type_name}")

    # 获取当前值的类型
    current_type = type(value)

    # 类型匹配则直接返回
    if current_type == target_type:
        return value

    # 类型不匹配时进行指针级转换
    src_ptr = pointer(value)
    casted_ptr = cast(src_ptr, POINTER(target_type))
    return casted_ptr.contents

def cast_ctypes_value(value, target_type):
    """智能类型转换函数"""
    if isinstance(value, target_type):
        return value
    
    # 指针类型特殊处理
    if isinstance(target_type, ctypes._Pointer):
        return ctypes.cast(ctypes.pointer(value), target_type)
    
    # 创建中间缓冲区进行二进制转换
    src_ptr = ctypes.pointer(ctypes.c_byte.from_buffer(value))
    dst_obj = target_type()
    ctypes.memmove(ctypes.pointer(dst_obj), src_ptr, min(ctypes.sizeof(value), ctypes.sizeof(target_type)))
    return dst_obj

def get_ctypes_type(type_node):
    """递归解析类型节点为ctypes类型"""
    if isinstance(type_node, c_ast.TypeDecl):
        return get_ctypes_type(type_node.type)
    elif isinstance(type_node, c_ast.IdentifierType):
        type_map = {
            'int': c_int,
            'float': c_float,
            'char': c_char,
            # 添加其他类型映射
        }
        return type_map[' '.join(type_node.names)]
    elif isinstance(type_node, c_ast.ArrayDecl):
        element_type = get_ctypes_type(type_node.type)
        return element_type
    # 处理指针等其他类型
    return c_int  # 默认类型

def get_typed_pointer(obj):
    """将ctypes对象转换为对应类型的指针"""
    # 获取对象类型（如c_int、c_float等）
    obj_type = type(obj)
    # 获取内存地址
    addr = addressof(obj)
    # 将地址转换为对应类型的指针
    ptr = cast(addr, POINTER(obj_type))
    return ptr

def apply_operator(a, b, op):
    a_val = a.value if isinstance(a, ctypes._SimpleCData) else a
    b_val = b.value if isinstance(b, ctypes._SimpleCData) else b
    
    if op == '+':
        res = a_val + b_val
    elif op == '-':
        res = a_val - b_val
    elif op == '*':
        res = a_val * b_val
    elif op == '/':
        res = a_val / b_val
    elif op == '<':
        return bool(a_val < b_val)
    elif op == '>':
        return bool(a_val > b_val)            
    return type(a)(res)

def cast_ctypes_value(value, target_type):
    """智能类型转换函数，支持以下转换场景：
    1. 基础类型转换（int->float等）
    2. 指针类型转换（int*->void*）
    3. 数组到指针的转换
    """
    # 类型完全匹配时直接返回
    if type(value) == target_type:
        return value
    
    # 处理指针类型转换
    if isinstance(target_type, ctypes._Pointer):
        # 获取指针实际指向的类型
        target_pointee = target_type._type_
        
        # 数组到指针的自动转换
        if isinstance(value, ctypes.Array):
            return cast(value, target_type)
            
        # 普通指针类型转换
        return cast(pointer(value), target_type)
    
    # 数值类型转换
    if isinstance(value, (c_int, c_float, c_double)):
        try:
            return target_type(value.value)
        except TypeError:
            # 二进制拷贝转换
            buf = (target_type * 1)()
            ctypes.memmove(
                buf, 
                ctypes.byref(value),
                min(ctypes.sizeof(value), ctypes.sizeof(target_type)))
            return buf[0]
    
    # 处理数组元素赋值
    if isinstance(value, ctypes.Array):
        return cast(value, target_type)
    
    raise TypeError(f"Cannot cast {type(value)} to {target_type}")

class LValue:
    def __init__(self, base, index=None, is_pointer=False):
        self.base = base     # 基础对象（变量/数组/指针）
        self.index = index   # 下标/成员名（可选）
        self.is_pointer = is_pointer  # 是否为指针解引用
    
    @property
    def value(self):
        if self.is_pointer:
            return self.base.contents
        if self.index is not None:
            return self.base[self.index]
        return self.base
    
    @value.setter
    def value(self, val):
        # 获取目标类型
        target_type = self._get_target_type()
        
        # 执行类型转换
        casted_val = cast_ctypes_value(val, target_type)
        # 实际写入内存（关键修改点）
        if self.is_pointer:
            # 直接修改指针指向的内存
            memmove(self.base, pointer(casted_val), sizeof(casted_val))
        elif self.index is not None:
            self.base[self.index] = casted_val
        else:
            # 修改基础对象的值
            self.base.value = casted_val.value
    
    def _get_target_type(self):
        """递归解析目标类型"""
        if self.is_pointer:
            # 处理多级指针（如int**）
            base = self.base
            while isinstance(base, LValue):
                if base.is_pointer:
                    base = base.base
                else:
                    break
            return base._type_  # 获取指针基础类型
        if self.index is not None:
            return type(self.base._type_())
        return type(self.base)

    
class Interpreter(c_ast.NodeVisitor):

    def __init__(self):
        self.memory = Memory()
        self.lvalue_context = None
    def load_libraries(self, tree):
        functions = get_functions('interpreter.__builtins__.stdio')

        for function in functions:
            self.memory[function.__name__] = function
        

    def visit_FileAST(self, node):
        # 根节点类型为FileAST
        for ext in node.ext:
            res = self.visit(ext)
            if isinstance(ext, (c_ast.FuncDef)) and ext.decl.name == 'main':
                return res

    def visit_ArrayRef(self, node):
        # 保存当前上下文状态
        prev_context = self.lvalue_context
        
        # 处理数组名称（始终为右值）
        self.lvalue_context = False
        array = self.visit(node.name)
        
        # 处理下标（右值）
        index = self.visit(node.subscript).value
        
        # 恢复上下文
        self.lvalue_context = prev_context
        
        if self.lvalue_context:
            # 左值上下文返回引用对象
            return LValue(array, index)
        else:
            # 右值上下文直接返回值
            return array[index]
    
    def _get_type_name(self, type_node):
        # 递归解析类型名称
        if isinstance(type_node, c_ast.TypeDecl):
            return self._get_type_name(type_node.type)
        elif isinstance(type_node, c_ast.IdentifierType):
            return ' '.join(type_node.names)
        return 'unknown'    
    def visit_Decl(self, node):
        """处理变量声明"""
        if isinstance(node.type, c_ast.TypeDecl):
            # 解析类型信息
            type_decl = node.type
            type_name = ' '.join(type_decl.type.names) if isinstance(type_decl.type, c_ast.IdentifierType) else 'int'
            
            # 获取初始值
            initial_value = get_ctypes_default_value(type_name)
            if node.init:
                initial_value = self.visit(node.init)
                initial_value = cast_ctypes_value(initial_value, get_ctypes_type(type_name))

            # 内存分配
            self.memory.declare(node.name)
            self.memory[node.name] = initial_value
        elif isinstance(node.type, c_ast.ArrayDecl):
            # 解析数组维度
            dim = self.visit(node.type.dim).value if node.type.dim else 0
            
            # 递归解析元素类型
            element_type = get_ctypes_type(node.type.type)
            
            # 创建数组类型
            array_type = element_type * dim
            
            # 处理初始化列表
            init_values = []
            if node.init:
                raw_values = self.visit(node.init)
                # 类型转换和填充
                for val in raw_values[:dim]:  # 截断超过维度的部分
                    if not isinstance(val, element_type):
                        val = cast_ctypes_value(val, element_type)
                    init_values.append(val)
            
            # 填充默认值
            init_values += [element_type()] * (dim - len(init_values))
            
            # 实例化数组
            arr = array_type(*init_values)
            
            # 注册到内存系统
            self.memory.declare(node.name, arr)
        elif isinstance(node.type, c_ast.PtrDecl):
            # 确保正确获取地址
            if node.init:
                # 处理 &a 的情况
                init_val = self.visit(node.init)
                self.memory.declare(node.name, init_val)
            else:
                # 默认空指针
                ptr_type = self._parse_type(node.type)
                self.memory.declare(node.name, ptr_type())
        # elif isinstance(node.type, c_ast.FuncDecl):
        #     # 处理函数声明（已在load_functions处理）
        #     self.memory[node.decl.name] = node
    
    def _parse_type(self, type_node):
        """递归解析类型为ctypes类型"""
        if isinstance(type_node, c_ast.PtrDecl):
            pointee_type = self._parse_type(type_node.type)
            return ctypes.POINTER(pointee_type)
        elif isinstance(type_node, c_ast.ArrayDecl):
            element_type = self._parse_type(type_node.type)
            return element_type * self.visit(type_node.dim).value
        elif isinstance(type_node, c_ast.TypeDecl):
            return self._parse_type(type_node.type)
        elif isinstance(type_node, c_ast.IdentifierType):
            type_map = {
                'int': c_int,
                'float': c_float,
                'char': c_char,
                # 其他类型...
            }
            return type_map[' '.join(type_node.names)]
        return c_int  # 默认类型

    def visit_IdentifierType(self, node):
        """处理类型标识符"""
        return ' '.join(node.names)
    def visit_Constant(self, node):
        """处理常量初始化"""
        if node.type == 'int':
            return get_ctypes_value('int', int(node.value))
        elif node.type == 'char':
            return get_ctypes_value('char', ord(node.value.strip("'")))
        elif node.type == 'float':
            return get_ctypes_value('float', float(node.value))
        elif node.type == 'string':
            # 去除引号并处理转义字符
            raw_str = node.value.strip('"')
            decoded_str = bytes(raw_str, 'latin-1').decode('unicode_escape')
            
            # 创建C风格字符串缓冲区（自动添加空终止符）
            c_str = ctypes.create_string_buffer(decoded_str.encode('latin-1'))
            return c_str
        else:
            raise TypeError('不支持的数据类型 %s' % node.type)

    def visit_InitList(self, node):
        """处理数组初始化列表"""
        return [self.visit(expr) for expr in node.exprs]

    def visit_ArrayDecl(self, node):
        """处理数组声明"""
        array_type = self.visit(node.type)
        array_size = self.visit(node.dim) if node.dim else 0
        return f'{array_type}[{array_size}]'

    def visit_Assignment(self, node):
        # 处理左值时设置上下文
        prev_context = self.lvalue_context
        self.lvalue_context = True
        lvalue = self.visit(node.lvalue)
        self.lvalue_context = prev_context

        rvalue = self.visit(node.rvalue)
        if node.op == '=':
            lvalue.value = rvalue
        else:
            op = node.op[:-1]
            current = lvalue.value
            lvalue.value = apply_operator(current, rvalue, op)
        return rvalue



    def visit_FuncDef(self, node):
        # 处理函数定义
        self.memory[node.decl.name] = node
        func_name = node.decl.name
        params = node.decl.type.args.params if node.decl.type.args else []

        self.memory.new_frame(func_name)
        for param in params:
            self.visit(param)  # 参数会通过Decl处理
        result = self.visit(node.body)
        self.memory.del_frame()
        return result

    def visit_Compound(self, node):
        self.memory.new_scope()
        for item in node.block_items:
            if isinstance(item, c_ast.Return):
                return self.visit(item)
            self.visit(item)
        self.memory.del_scope()

    def visit_FuncCall(self, node):
        # 函数调用节点
        func_name = node.name.name
        args = [self.visit(arg) for arg in node.args]
        if func_name == "scanf":
            args.append(self.memory)
        
        if isinstance(self.memory[func_name], c_ast.FuncDef):
            self.memory.new_frame(func_name)

            # 绑定参数
            params = self.memory[func_name].decl.type.args.params
            for param, arg in zip(params, args):
                self.memory[param.name] = arg

            result = self.visit(self.memory[func_name].body)
            self.memory.del_frame()
            return result
        else:
            return ctypes.c_int(self.memory[func_name](*args))

    def visit_UnaryOp(self, node):
        """处理一元操作符，完全基于ctypes类型系统"""
        operator = node.op
        
        # 处理前置递增 ++a
        if operator == "++":
            # 获取左值引用
            prev_context = self.lvalue_context
            self.lvalue_context = True
            lvalue = self.visit(node.expr)
            self.lvalue_context = prev_context
            
            # 执行递增操作
            new_value = ctypes.cast(
                ctypes.pointer(lvalue.value), 
                ctypes.POINTER(type(lvalue.value)))
            new_value.contents.value += 1
            return new_value.contents
        
        # 处理后置递增 a++
        elif operator == "p++":
            # 先获取当前值
            prev_context = self.lvalue_context
            self.lvalue_context = False
            original_value = self.visit(node.expr)
            self.lvalue_context = prev_context
            
            # 执行递增操作
            lvalue = self.visit(node.expr)
            lvalue.value = original_value.value + 1
            return original_value
        
        # 处理前置递减 --a
        elif operator == "--":
            # 获取左值引用
            prev_context = self.lvalue_context
            self.lvalue_context = True
            lvalue = self.visit(node.expr)
            self.lvalue_context = prev_context
            
            # 执行递减操作
            new_value = ctypes.cast(
                ctypes.pointer(lvalue.value),
                ctypes.POINTER(type(lvalue.value)))
            new_value.contents.value -= 1
            return new_value.contents
        
        # 处理负号 -
        elif operator == '-':
            operand = self.visit(node.expr)
            # 通过内存拷贝保证类型正确性
            target_type = type(operand)
            buf = ctypes.create_string_buffer(ctypes.sizeof(target_type))
            ctypes.memmove(buf, ctypes.byref(operand), ctypes.sizeof(target_type))
            
            # 对二进制数据取反（需根据类型处理）
            if target_type in (c_int, c_short, c_long):
                inverted = -ctypes.cast(buf, ctypes.POINTER(target_type)).contents.value
            elif target_type in (c_float, c_double):
                inverted = -ctypes.cast(buf, ctypes.POINTER(target_type)).contents.value
            else:
                raise TypeError(f"Unsupported type for negation: {target_type}")
            
            return target_type(inverted)
        
        # 处理逻辑非 !
        elif operator == "!":
            operand = self.visit(node.expr)
            # 根据C语言规则：0为假，非0为真
            return c_int(1 if operand.value == 0 else 0)
        elif node.op == '&':
            # 获取变量的内存地址
            var = self.visit(node.expr)
            ptr = get_typed_pointer(var)
            return ptr
        elif node.op == '*':
            # 确保在右值上下文获取指针对象
            prev_context = self.lvalue_context
            self.lvalue_context = False
            ptr = self.visit(node.expr)
            self.lvalue_context = prev_context
            
            # 处理多级指针解引用
            while isinstance(ptr, LValue):
                ptr = ptr.value
                
            if not isinstance(ptr, ctypes._Pointer):
                raise TypeError(f"Operand of * must be pointer, got {type(ptr)}")
                
            return LValue(ptr, is_pointer=True)
         # 处理sizeof运算符（需要单独实现）
        elif operator == 'sizeof':
            # 此处需要类型推导的增强实现
            target_type = self._parse_type(node.expr.type)
            return c_size_t(ctypes.sizeof(target_type))
        
        else:
            raise NotImplementedError(f"Unary operator {operator} not supported")

    def visit_ID(self, node):
        """修正ID访问逻辑"""
        # 获取原始值
        raw_value = self.memory[node.name]
        # 根据上下文决定返回类型
        if self.lvalue_context:
            # 当作为左值时返回可修改的引用
            if isinstance(raw_value, ctypes.Array):
                return LValue(raw_value)
            return LValue(raw_value)
        else:
            # 直接返回存储的ctypes对象
            return raw_value

    def visit_BinaryOp(self, node):
        return apply_operator(self.visit(node.left), self.visit(node.right), node.op)

    def visit_If(self, node):
        if self.visit(node.cond):
            self.visit(node.iftrue)
        elif node.iffalse:
            self.visit(node.iffalse)

    def visit_While(self, node):
        while self.visit(node.cond):
            self.visit(node.stmt)

    def visit_For(self, node):
        self.visit(node.init)
        while self.visit(node.cond):
            self.visit(node.stmt)
            self.visit(node.next)

    def visit_Return(self, node):
        # 确保返回表达式在右值上下文
        prev_context = self.lvalue_context
        self.lvalue_context = False
        value = self.visit(node.expr) if node.expr else None
        self.lvalue_context = prev_context
        return value

    def visit_EmptyStatement(self, node):
        pass

    def interpret(self, ast):
        self.load_libraries(ast)
        # print(self.memory)
        res = self.visit(ast)
        return res

    @staticmethod
    def run(code):
        parser = c_parser.CParser()
        ast = parser.parse(code)
        # print(ast)
        status = Interpreter().interpret(ast)
        print(
            MessageColor.OKBLUE
            + "Process terminated with status {}".format(status)
            + MessageColor.ENDC
        )
